package com.bitrate.dagger.redis.config;

import java.util.Map;
import java.util.NoSuchElementException;
import java.util.concurrent.ConcurrentHashMap;

import javax.annotation.PostConstruct;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.core.env.Environment;
import org.springframework.data.redis.core.RedisTemplate;

import com.bitrate.dagger.redis.context.RedisManager;
import com.bitrate.dagger.redis.core.RedisRegister;
import com.bitrate.dagger.redis.entity.RedisEntity;


@AutoConfigureBefore({ RedisAutoConfiguration.class })
@Import(RedisRegister.class)
@EnableCaching
@Configuration
public class RedisConfiguration implements EnvironmentAware,
		ApplicationContextAware {

	private static final Logger logger = LoggerFactory
			.getLogger(RedisConfiguration.class);

	private static String TEMP_KEY = "redisTemplate";

	ConcurrentHashMap<String, RedisTemplate<String, Object>> redisTemplateMap = new ConcurrentHashMap<String, RedisTemplate<String, Object>>();

	private Binder binder;

	private Environment environment;

	@Override
	public void setEnvironment(Environment environment) {
		this.environment = environment;
		this.binder = Binder.get(this.environment);
	}

	@PostConstruct
	public Map<String, RedisTemplate<String, Object>> initRedisTemplate() {
		RedisEntity redisEntity;
		try {
			redisEntity = binder.bind("x.redis", RedisEntity.class).get();
		} catch (NoSuchElementException e) {
			throw new RuntimeException(
					"Failed to configure x redis: 'x.redis' attribute is not specified and no embedded redis could be configured.");
		}

		// 根据多个库实例化出多个连接池和Template
		String databaseStr = redisEntity.getDatabases();
		String[] databaseArr = databaseStr.split(",");
		for (String database : databaseArr) {
			String key = TEMP_KEY + database;
			RedisTemplate<String, Object> redisTemplate = applicationContext.getBean(key, RedisTemplate.class);
			if (redisTemplate != null) {
				logger.info("init RedisTemplate Database {} Success !!!!",database);
				redisTemplateMap.put(key, redisTemplate);
			}
		}
		if (redisTemplateMap.size() == 0) {
			throw new RuntimeException(
					"load redisTemplate failure , please check x.redis property config！！！");
		}
		return redisTemplateMap;
	}

	private ApplicationContext applicationContext;

	@Override
	public void setApplicationContext(ApplicationContext applicationContext)
			throws BeansException {
		this.applicationContext = applicationContext;
	}

	@Bean
	public RedisManager redisManager() {
		return new RedisManager(redisTemplateMap);
	}

}
